home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / xdme_1.84_src.lha / XDME / Src / Mod / Alias.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-05  |  21.3 KB  |  796 lines

  1. /******************************************************************************
  2.  
  3.     MODUL
  4.     $Id: alias.c $
  5.  
  6.     DESCRIPTION
  7.     macros for XDME
  8.  
  9.     NOTES
  10.     a part of that module is in command.c
  11.  
  12.     BUGS
  13.     <none known>
  14.  
  15.     TODO
  16.     -/-
  17.  
  18.     EXAMPLES
  19.     -/-
  20.  
  21.     SEE ALSO
  22.     command.c
  23.  
  24.     AUTHOR
  25.     Bernd "0" Noll (b_noll@informatik.uni-kl.de)
  26.  
  27.     HISTORY
  28.     $Log: alias.c $
  29.     21-09-94 b_noll added DEFCMD/DEFHELP-support
  30.     24-09-94 b_noll usage of std_-read/write-file
  31.     01-10-94 b_noll introduced DEFMESSAGE
  32.     16-11-94 b_noll added GetMVBase
  33.     22-11-94 b_noll removed getmacroarg - args are normal vars now
  34.     23-11-94 b_noll removed getmacrovar - done from vars.c now
  35.     04-12-94 b_noll removed some dead protos
  36.  
  37.  
  38. ******************************************************************************/
  39.  
  40. /*
  41. **  (C)Copyright 1992 by Bernd Noll for null/zero-soft
  42. **  All Rights Reserved
  43. **
  44. **  RCS Header: $Id: Alias.c 1.2 1994/09/20 11:05:32 b_noll Exp b_noll $
  45. **
  46. **  compiling with
  47. **  "#define PATCH_NULL"
  48. **  "#define PATCH_MACROS"
  49. **  causes that module to be used
  50. **
  51. *!*********************************************************************
  52. *!
  53. *!  MACROS - OVERVIEW
  54. **
  55. **  this option allows translation of alias.c
  56. **  and enables a change in do_command() to allow macro-execution
  57. **  and (perhaps) one in main() to initialize the macro-lists
  58. *!
  59. *!  the module supports several commands:
  60. *!  SETMACRO        definition of a new macro
  61. *!  UNSETMACRO        deletion of a macro
  62. *!
  63. *!  SETMACROVAR     definition of a macro's local variable
  64. *!  UNSETMACROVAR    deletion of suh a variable
  65. *!            (at the end of a macrocall all its local variables
  66. *!             are deleted automatically)
  67. *!
  68. **********************************************************************/
  69.  
  70.  
  71. /**************************************
  72.         Includes
  73. **************************************/
  74. #define MACRO struct MacroNode /* OPAQUE 4 other modules */
  75. #include "defs.h"
  76. #include "AVL.h"
  77.  
  78. DEFDEFINITION( PATCH_ALIAS 1 )
  79.  
  80. /* ngra - the straight avl module is broken ... */
  81. int iAVL_Append (APTR x, APTR y, APTR z);
  82. int iAVL_Remove (APTR x, APTR y, APTR z);
  83. int iAVL_Find    (APTR x, APTR y, APTR z);
  84.  
  85. #define ANY_Find(t,n)   iAVL_Find  (t,(APTR)NodeStringComparison, n)
  86. #define ANY_Add(t,n)    iAVL_Append(t,(APTR)NodeNodeComparison,   n)
  87. #define ANY_Remove(t,n) iAVL_Remove(t,(APTR)NodeNodeComparison,   n)
  88. #define ANY_Init(t)     *(t) = NULL;
  89.  
  90. /**************************************
  91.       Interne Defines & Struktures
  92. **************************************/
  93. /*
  94. ** U might use MACRO like an opaque type
  95. */
  96.  
  97. struct MacroNode {
  98.     struct Node Node;   /* includes a ptr to the macro-name */
  99.     char*        Body;   /* statements to be executed at a macro-call (this all must fit in one line) */
  100.     char        NArgs;  /* 0..7 number of arguments to be given from do_command */
  101.     //short     NFlags; /* PERHAPS FUTURE: 0..n number of local-flags to be supported */
  102.     //char        freeme; /* NOT USED ANY MORE 0/1 flag if the macro is builtin or user-defined */
  103.     char        killme; /* 0/1 flag if he maxro shall be deleted after termination of its last macrocall */
  104.     char        NCalls; /* it seems to be necessary to forbid all deletions of an active macro */
  105. };
  106.  
  107. struct MacroArg {
  108.     struct MinNode     ma_Node;     /* hook for recursion-stack */
  109.     struct MacroNode*ma_Macro;     /* a reference to the called macro w/ all its data */
  110.     VarRoot      ma_Locals;     /* AVL-Tree or List of Local Variables */ /* we could also have a ptr to an array of ptrs instead of a list, but then it might be necessary to use one more parameter for SETMACRO */
  111.     //char*        ma_Arguments[2];/* NOT USED ANY MORE array of ptr to string; there must always be at least two entries: a 1st one referencing the macroname and a last one == NULL */
  112. };
  113.  
  114. /**************************************
  115.         Internal Variables
  116. **************************************/
  117.     /*
  118.     **    *argstack contains all data which is created during one macro-call
  119.     **    *delenda is a delete-buffer for all macros, will have been removed
  120.     **     from their lists, but cannot deleted, as there is a prior call to
  121.     **     not returned; they are deleted then aftermacro-termination or
  122.     **     in exit_macros.
  123.     */
  124. static struct TreeNode* macros = NULL;    /* ... OF MACRO */
  125. static struct TreeNode* delenda= NULL;    /* ... OF MACRO */
  126. static MLIST argstack;            /* ... OF struct MacroArg */
  127. char  MacroBreak = 0;            /* internal possibility to terminate a macro */ /* PATCH_NULL [08 Mar 1993] : removed "static" */
  128.  
  129. /**********************************************
  130. **
  131. **  Definition and deletion of Macros
  132. **
  133. **********************************************/
  134.  
  135.  
  136. /*
  137. **  FreeMacro()
  138. **  DelMacro()
  139. **    2 help-Functions of do_unsetmacro (and exit_macros)
  140. **
  141. **    DelMacro() should delete only Macros, which are not in use
  142. **    for that reason it checks usecount, and if its not 0, the
  143. **    macro is put into another list and marked to be killed by
  144. **    callmacro() after execution.
  145. */
  146.  
  147. static void FreeMacro(MACRO *m) {
  148.     //if (m->freeme) {                    /* if that macro is not a builtin one, */
  149.     free(m->Node.ln_Name);          /* free it and its contents */
  150.     free(m->Body);
  151.     free(m);
  152.     //} /* if */
  153. } /* FreeMacro */
  154.  
  155.  
  156. static void DelMacro (char *name) {
  157.     MACRO *m;
  158.  
  159.     if ((m = getmacro(name))) {         /* find the node representing the macro ... */
  160.     ANY_Remove (¯os, (APTR)m);  /* , remove it from its tree ... */
  161.     if (!m->NCalls) {               /* and if it is not in use */
  162.         FreeMacro(m);               /* ... free its contents */
  163.     } else {            /* ... else put it into a certain kill-list */
  164.         m->killme++;        /* ... and mark it to be killed */
  165.         ANY_Add (&delenda, (APTR)m);
  166.     } /* if */
  167.     } /* if */
  168. } /* DelMacro */
  169.  
  170.  
  171.  
  172. /*
  173. **  SetMacro()
  174. **    a help-Function of do_setmacro (and maybe init_macros)
  175. **    (it is also called by packages.mergpack)
  176. **    which creates a new macro-node and fills copies of the parameters
  177. **
  178. */
  179.  
  180. static int SetMacro(char *name, char *body, int nargs) {
  181.     MACRO *m;
  182.     if (nargs >= NARGS) {
  183. DEFMESSAGE( _MACRO_too_many_arguments, "too many arguments specified for macro" )
  184.     error (_MACRO_too_many_arguments);
  185.     return(0);
  186.     } /* if too many args */
  187.  
  188.     DelMacro(name);                                         /* for sure: remove all macros of the same name */
  189.  
  190.     if ((m = malloc(sizeof(MACRO)))) {                      /* allocate a macro-structure... */
  191.     setmem(m, sizeof(MACRO),0);
  192.     if ((m->Node.ln_Name = strdup(name))) {             /* ... the name ... */
  193.         if ((m->Body  = strdup(body))) {                /* ... and the body, */
  194.         m->NArgs  = nargs;                /* fill in all values,  */
  195.         //m->freeme = 1;
  196.         ANY_Add (¯os, (APTR)m);                 /* and append the structure to a certain macro-list */
  197.         return 1;
  198.         } /* if block copied */
  199.         free(m->Node.ln_Name);                          /* if anything went wrong */
  200.     } /* if name copied */                    /* free all allocated frags */
  201.     free(m);                                            /* and set an error */
  202.     } /* if struct allocated */
  203.     nomemory();
  204.     return 0;
  205. } /* SetMacro */
  206.  
  207.  
  208.  
  209. /**********************************************
  210. **
  211. **  Access to Macros' arguments and local variables
  212. **
  213. **********************************************/
  214.  
  215. DEFVARTREE( 50, "MVAR_", VAR_MV, 5, 5, VF_COP|VF_UD_FUNC, GetMVBase, NULL, SetVarIntoTree, GetVarFromTree )
  216.  
  217. Prototype VBASE *GetMVBase (void);
  218. VBASE *GetMVBase (void) {
  219.     struct MacroArg* n;
  220.     if (!(n = GetHead(&argstack)))
  221.     return NULL;
  222.     return &n->ma_Locals;
  223. } /* GetMVBase */
  224.  
  225.  
  226.  
  227. #if 0
  228.  
  229. /*
  230. **  SetMacroVar()
  231. **    a help-function of do_setmacrovar()
  232. */
  233.  
  234. void SetMacroVar(char *name, char *value) {
  235.     VBASE* v;
  236.  
  237.     if (!(v = GetMVBase())) /* this function can not work if not called from within a macrocall */
  238.     SET_ABORTION( 1 );
  239.     else
  240.     SetVarIntoTree (v, name, value);
  241. } /* SetMacroVar */
  242.  
  243. /*
  244. **  getmacrovar()
  245. **    get a local variable of the current(== last) macrocall
  246. **    we are supposing that only one process has access to resources
  247. **    that function is meant to be interface for getvar()
  248. */
  249.  
  250. UBYTE *getmacrovar(UBYTE *name)
  251. {
  252.     return GetVarFromTree (GetMVBase(), name);
  253. } /* getmacrovar */
  254.  
  255.  
  256. /* !!!this function is obsolete, since we handle macroargs like macrovars!!!!!!!
  257. **  getmacroarg()
  258. **    get an parameter of the current(== last) macrocall
  259. **    we are supposing that only one process has access to resources
  260. **    so we only have to check the topmost element of argstack
  261. *!  NOTE:   ARGUMENTS to a macro are READ-ONLY,
  262. *!        You can't alter their values from the body of the called macro
  263. *!
  264. */
  265. UBYTE *getmacroarg(UBYTE *name)
  266. {
  267.     struct MacroArg* n;
  268.     int num;
  269.     UBYTE *res;
  270.  
  271.     if (!(n = GetHead(&argstack))) /* this function can not work if not called from within a macrocall */
  272.     return NULL;
  273.  
  274.  
  275.     if ((strncmp(name,"arg",3) != 0) || (!is_number(name+3))) {     /* and it responds only to names of the type "ARGx" with x in /N */
  276.     return(NULL);
  277.     } /* if */
  278.     num = atoi(name+3);
  279.  
  280.     if (n->ma_Macro->NArgs>=num) {                                     /* if the last called function has an arg ARGx */
  281.     if ((res = strdup (n->ma_Arguments[num]))) {                   /* and U can duplicate it, then return the copy */
  282.         return(res);
  283.     } else {
  284.         nomemory();
  285.         abort(NULL);
  286.     } /* if (not) malloced res */
  287.     } else {
  288.     abort(NULL);
  289.     } /* if (not) exists argX */
  290. } /* getmacroarg */
  291.  
  292. /*
  293. **  That function might be used as an interface for getvar
  294. **  to access the contents of a macro
  295. */
  296.  
  297. char *GetFuncBody(char *name)
  298. {
  299.     MACRO* m = NULL;
  300.     char* str = NULL;
  301.  
  302.     if (m = (MACRO*)getmacro(name)) {
  303.     str = strdup(m->Body);
  304.     } /* if */
  305.     return(str);
  306. } /* GetFuncBody */
  307.  
  308. #endif
  309.  
  310.  
  311.  
  312. /**********************************************
  313. **
  314. **  Usage of Macros
  315. **
  316. **  for calls from do_command the sequence must
  317. **  be like that:
  318. **
  319. **  if (m=getmacro) then
  320. **    for i=1 to nummacroargs(m) do
  321. **        put nextarg to av[i]
  322. **    od;
  323. **    callmacro(m);
  324. **  fi;
  325. **
  326. **  callmacro() pushes av[i] onto argstack and
  327. **  clears them, then locks the macro and
  328. **  calls do_command with a copy of the
  329. **  macro's block
  330. **  when the execution returns, av[i] are
  331. **  restored and top of argstack is cleared
  332. **
  333. **********************************************/
  334.  
  335.  
  336. /*
  337. **  callmacro()
  338. **    Call a Macro as interface from do_command()
  339. **    (first you must have got a "handle" via getmacro())
  340. */
  341.  
  342. Prototype int callmacro (MACRO*);
  343. int callmacro (MACRO *m)
  344. {
  345.     struct MacroArg *n;
  346.     //char** args;
  347.     int ret    = 0;
  348.     int i;
  349.     int len    = sizeof(struct MacroArg);
  350.  
  351.     n    = (struct MacroArg*)malloc(len);                     /* allocate space for the stack-element... */
  352.  
  353.     if (n) {
  354.     setmem(n,len,0);                        /* clear all data */
  355.     AddHead((LIST*)&argstack,(NODE*)n);     /* and push the struct to argstack */
  356.  
  357.     InitVars (&n->ma_Locals);                  /* for use with encapsulated local variables we must initialize their list */
  358.  
  359.     av[0] = m->Node.ln_Name;        /* define argslot 0 - it might be asked during execution, and perhaps it was not set in do_command */
  360.     for (i = m->NArgs; i >= 0; i--) {
  361.         char nam[6] = "arg0";
  362.         nam[3] += i;
  363.         SetVarIntoTree (&n->ma_Locals, nam, av[i]);/* then put all arguments into the struct */
  364.         //av[i] = NULL;              /* and clear their global values */
  365.     } /* for */
  366.  
  367. //AVL_ScanTree (&n->ma_Locals, PrintNode, 1);
  368.  
  369.     n->ma_Macro = m;
  370.     m->NCalls++;                /* disable deletion of that macro during execution */
  371.  
  372.     MacroBreak = 0;             /* clear the return - flag */
  373.  
  374.     ret = buffered_do_command(m->Body);     /* and call the macrobody */
  375.     if (MacroBreak) {
  376.         ret = 1-ret;
  377.         SET_ABORTION( MacroBreak == 2 );
  378.         MacroBreak     = 0;
  379.     } /* if */
  380.  
  381.     //for (i = m->NArgs; i >= 0; i--) {       /* after the call restore the global values of all args, ... */
  382.     //    av[i] = args[i];
  383.     //} /* for */
  384.     m->NCalls--;                /* and enable deletion of that macro after execution */
  385.     if (m->NCalls == 0 && m->killme) {      /* if we must delete the macro, do it */
  386.         ANY_Remove(&delenda, (APTR)m);
  387.         FreeMacro(m);
  388.     } /* if */
  389.  
  390.     DelAllVarsFromTree (&n->ma_Locals);     /* delete all local variables ... */
  391.  
  392.     Remove((NODE*)n);                       /* and pop the margs-struct from argstack */
  393.     } else
  394.     nomemory();
  395.  
  396.     if (n)                                      /* and free anything you allocated */
  397.     free(n);
  398.  
  399.     return ret;
  400. } /* callmacro */
  401.  
  402.  
  403.  
  404. /*
  405. **  getmacro()
  406. **
  407. **    Find a Function of a given Name
  408. **    so macros can be tested for existance and user can get a ptr to a "Handle"
  409. **    that function is part of the interface to do_command()
  410. */
  411.  
  412. Prototype MACRO *getmacro (char *name);
  413. MACRO *getmacro(char *name) {
  414.     MACRO *m;
  415.  
  416.     m = (MACRO *)ANY_Find (¯os, name);
  417.     return m;
  418. } /* getmacro */
  419.  
  420.  
  421. /*
  422. **  nummacroargs()
  423. **    Get the Number of Arguments of a Macro
  424. **    that function is used by do_command to get informations
  425. **    how many argslots to fill
  426. */
  427.  
  428. Prototype int nummacroargs (MACRO *);
  429. int nummacroargs (MACRO *m) {
  430.     return m? (m->NArgs): 0;
  431. } /* nummacroargs */
  432.  
  433.  
  434.  
  435. /**********************************************
  436. **
  437. **  Initial Access to Macros
  438. **
  439. **********************************************/
  440.  
  441.  
  442. #if 0
  443. /* support of default macros has been dropped, since there is imho no really */
  444. /* need for it                                     */
  445.  
  446. /*
  447. **  resmacros
  448. **    that structure shows all builtin macros
  449. **    which are defined at program start
  450. **    they are initialized via GetDefMacros
  451. */
  452.  
  453. typedef struct _mres
  454. {
  455.     char * name;
  456.     char * body;
  457.     int   numargs;
  458. } MRES;
  459.  
  460. static CONST MRES resmacros[] =
  461. {
  462.      /*  name,        block,              args */
  463.  
  464.     { "alias",       "setmacro   $arg1 0 $arg2", 2 },
  465.     { "aslload",     "arpload",                  0 },
  466.     { "aslinsfile",  "arpinsfile",               0 },
  467.     { "aslfont",     "arpfont",                  0 },
  468.     { "aslsave",     "arpsave",                  0 },
  469.     /* { "asl",     "arp",                  0 }, */
  470.     { "unalias",     "unsetmacro $arg1",         1 },
  471.     { "firstwindow", "select f",                 0 },
  472.     { "lastwindow",  "select l",                 0 },
  473.     { "nextwindow",  "select n",                 0 },
  474.     { "prevwindow",  "select p",                 0 },
  475.     { "so",          "if m saveold",             0 },
  476.     { NULL,      NULL,                 0 }
  477. }; /* resmacros */
  478.  
  479.  
  480. /*
  481. **  GetDefMacros
  482. **    initialize the builtin default-macros
  483. */
  484.  
  485. static int GetDefMacros (void)
  486. {
  487.     int i;
  488.  
  489.     for (i = 0; resmacros[i].name; i++) {
  490.     if (!SetMacro(resmacros[i].name, resmacros[i].body, resmacros[i].numargs)) {
  491.         return (0);
  492.     } /* if error */
  493.     } /* for all builtins */
  494.  
  495.     return (1);
  496. } /* GetDefMacros */
  497.  
  498. #else
  499. #define GetDefMacros()
  500. #endif
  501.  
  502.  
  503. /*
  504. **  ALIAS_init ()
  505. **
  506. **    Init All Macro-Stuff
  507. **        init all name-lists
  508. **        init the arg-stack
  509. **        enable the builtin macros (if macros are global)
  510. **
  511. **    That function has to be called at programstart
  512. */
  513.  
  514. DEFAUTOINIT( ALIAS_Init )
  515. {
  516.     NewList ((LIST*)&argstack);
  517.  
  518.     ANY_Init (&delenda);
  519.     ANY_Init (¯os);
  520.  
  521.     GetDefMacros ();
  522. } /* init_macros */
  523.  
  524.  
  525.  
  526. /**********************************************
  527. **
  528. **  IO of Macros (dumping)
  529. **
  530. **********************************************/
  531.  
  532.  
  533. /* That static variable is needed to communicate between savesinglemacro and savemacros */
  534. static FILE * mfi;
  535.  
  536. static void savesinglemacro (MACRO *m)
  537. {
  538.     if (m && mfi) {
  539.     fprintf (mfi, "\tMACRO %s\n", m->Node.ln_Name);
  540.     if (m->NArgs) {
  541.         fprintf (mfi, "\t ARGS %d\n", m->NArgs);
  542.     } /* if */
  543.     fprintf (mfi, "\t BODY %s\n", m->Body);
  544.     } /* if */
  545. } /* savesinglemacro */
  546.  
  547. static int ALIAS_save (FILE *fo)
  548. {
  549.     fprintf(fo, "MACROS START\n");
  550.  
  551.     mfi = fo;
  552.     AVL_ScanTree (¯os, (APTR)savesinglemacro, 1);
  553.  
  554.     fprintf(fo, "MACROS END\n");
  555.     return (1);
  556. } /* savemacros */
  557.  
  558.  
  559.  
  560. static int ALIAS_load (FILE *fi, int *lineno)
  561. {
  562.     char  *buf;
  563.     char   nmacro [128];
  564.     char   nargs  [128];
  565.     char   body   [2*LINE_LENGTH];
  566.  
  567.     buf = getnextcomline(fi, lineno);
  568.     if (!buf) {
  569.     abort(0);
  570.     } /* if */
  571.     if (strncmp(buf, "MACROS START", 12) != 0) {
  572. DEFMESSAGE( _MACRO_read_no_header, "No Macrostart header" )
  573.     error (_MACRO_read_no_header);
  574.     abort(0);
  575.     } /* if */
  576.  
  577.     nmacro[0] = 0;
  578.     nargs [0] = 0;
  579.     body  [0] = 0;
  580.  
  581.     while (!IS_ABORTED()) {
  582.     buf = getnextcomline(fi, lineno);
  583.     if (!buf) {
  584.         abort(0);
  585.     } /* if */
  586.  
  587.     if (strncmp(buf, "MACROS END", 10) == 0) {
  588.         return(1);
  589.     } else if (strncmp(buf, "MACRO ", 6) == 0) {
  590.         buf += 6;
  591.         strncpy(nmacro, buf, 128);
  592.     } else if (strncmp(buf, "ARGS ", 5) == 0) {
  593.         buf += 5;
  594.         if (nargs[0] != 0) {
  595. DEFMESSAGE( _MACRO_read_numargs_wo_name, "%s:\nDeclared numargs not w/in a Macro" )
  596.         error(_MACRO_read_numargs_wo_name, av[0]);
  597.         abort(0);
  598.         } /* if */
  599.         strncpy(nargs, buf, 128);
  600.     } else if (strncmp(buf, "BEGIN", 5) == 0) {
  601.         int len = 0;
  602.  
  603.         buf += 5;
  604.         while (*buf && *buf<33) buf++;
  605.         if (nmacro[0] == 0) {
  606. DEFMESSAGE( _MACRO_read_body_wo_name, "<%s:\nDeclared Body w/out Macro" )
  607.         error(_MACRO_read_body_wo_name, av[0]);
  608.         abort(0);
  609.         } /* if */
  610.  
  611.         if (*buf) {
  612.         len = strlen(buf);
  613.         strcpy (body, buf);
  614.         } /* if */
  615.  
  616.         while ((!IS_ABORTED()) && (buf = getnextcomline(fi, lineno))) {
  617.         char * inter = &body[len];
  618.         if (strncmp (buf, "END", 3) == 0) {
  619.             goto setit;
  620.         } /* if */
  621.         len += strlen(buf)+1;
  622.         if (len < 2*LINE_LENGTH) {
  623.             *inter = ' ';
  624.             strcpy(inter+1, buf);
  625.         } else {
  626. DEFMESSAGE( _MACRO_read_body_too_big, "%s:\nmacro-body too long" )
  627.             error (_MACRO_read_body_too_big, av[0]);
  628.         } /* if */
  629.         } /* while */
  630.         goto retfail;
  631.  
  632.     } else if (strncmp(buf, "BODY", 4) == 0 && (buf[4] < 0x21)) {
  633.         buf += 4;
  634.         if (*buf) buf++;
  635.         if (nmacro[0] == 0) {
  636. DEFMESSAGE( _MACRO_read_body_wo_macro, "<%s:\nDeclared Body w/out Macro" )
  637.         error(_MACRO_read_body_wo_macro, av[0]);
  638.         abort(0);
  639.         } /* if */
  640.         strncpy(body, buf, 2*LINE_LENGTH);
  641. setit:
  642.         av[1] = nmacro;
  643.         av[2] = nargs[0] ? nargs : "0";
  644.         av[3] = body;
  645.         do_setmacro();
  646.         nmacro[0] = 0;
  647.         nargs [0] = 0;
  648.     } else {
  649. DEFMESSAGE( _MACRO_read_unknown_id, "%s:\nunknown identifier '%s'" )
  650.         error(_MACRO_read_unknown_id, av[0], buf);
  651.     } /* if types */
  652.     } /* while not ready */
  653.  
  654. retfail:
  655.     return(0);
  656. } /* loadmacros */
  657.  
  658.  
  659.  
  660.  
  661.  
  662. /***************************************************
  663.  
  664.         XDME COMMAND INTERFACE
  665.  
  666. ***************************************************/
  667.  
  668.  
  669. /*
  670. *! >SETMACROVAR name value
  671. *! >SMV     name value
  672. *!    define a local variable for the current macro-call
  673. *!    all local vars will be deleted at the end of a macro-execution
  674. *!    (SMV is a shortcut for SETMACROVAR as we can't define a short
  675. *!     macro for that command)
  676. *!
  677. */
  678.  
  679. /*DEFHELP #cmd macro,var SMV name value - short for @{B}SETMACROVAR@{UB} */
  680. /*DEFHELP #cmd macro,var SETMACROVAR name value - create/modify a macrolocal variable inside a macro */
  681. DEFUSERCMD("SMV",         2, CF_VWM|CF_ICO|CF_COK, void, do_setmacrovar, (void),;)
  682. DEFUSERCMD("SetMacroVar", 2, CF_VWM|CF_ICO|CF_COK, void, do_setmacrovar, (void),)
  683. {
  684.     VBASE *v;
  685.  
  686.     if (!(v = GetMVBase())) /* this function can not work if not called from within a macrocall */
  687.     SET_ABORTION( 1 );
  688.     else
  689.     SetVarIntoTree (v, av[1], av[2]);
  690. } /* do_setmacrovar */
  691.  
  692.  
  693. /*
  694. *! >UNSETMACROVAR name
  695. *!    drop a local variable before the end of the current macro-call
  696. *!    all local vars will be deleted at the end of a macro-execution
  697. *!    so that command may be obsolete
  698. *!
  699. */
  700.  
  701. /*DEFHELP #cmd macro,var UNSETMACROVAR name - deletion of a macro's local variable */
  702. DEFUSERCMD("UnsetMacroVar", 1, CF_VWM|CF_ICO|CF_COK, void, do_unsetmacrovar, (void),)
  703. {
  704.     VBASE *v;
  705.  
  706.     if (!(v = GetMVBase())) /* this function can not work if not called from within a macrocall */
  707.     SET_ABORTION( 1 );
  708.     else
  709.     DelVarFromTree (v, av[1]);
  710. } /* do_unsetmacrovar */
  711.  
  712.  
  713. /*
  714. *! >RET
  715. *!    Terminate the current macro
  716. *!
  717. */
  718.  
  719. /*DEFHELP #cmd macro RET - terminate a macro (before reaching its end) */
  720. DEFUSERCMD("Ret", 0, CF_VWM|CF_ICO|CF_COK, void, do_retmacro, (void),)
  721. {
  722.     MacroBreak = IS_ABORTED() ? 2 : 1;
  723.     SET_ABORTION(1);
  724. } /* do_retmacro */
  725.  
  726.  
  727. /*
  728. *! >SETMACRO macroname numargs body
  729. *!    create a macro definition
  730. *!    please note that a macro-body is read twice once on definition
  731. *!    and once on execution (variables should be excaped so)
  732. *!
  733. *!    after such a definition it is possible to use macroname like
  734. *!    any XDME-command; the following numargs expressions are used
  735. *!    as the macros variables, they can be accessed for read with
  736. *!    $arg0-$arg<numargs> (not for write)($arg0 returns the macro's
  737. *!    name)
  738. *!
  739. *!  BUG:    if numargs is not a number then this command
  740. *!        will assume a value of "0"
  741. */
  742.  
  743. /*DEFHELP #cmd macro SETMACRO name nargs body - create/modify the commandmacro @{B}name@{UB} with @{B}nargs@{UB} arguments */
  744. DEFUSERCMD("SetMacro", 3, CF_VWM|CF_ICO|CF_COK, void, do_setmacro, (void),)
  745. {
  746.     SetMacro (av[1], av[3], atoi(av[2]));
  747. } /* do_setmacro */
  748.  
  749.  
  750. /*
  751. *!  >UNSETMACRO name
  752. *!    remove a macro definition
  753. *!
  754. */
  755.  
  756. /*DEFHELP #cmd macro UNSETMACRO name - delete the commandmacro @{B}name@{UB} */
  757. DEFUSERCMD("UnsetMacro", 1, CF_VWM|CF_ICO|CF_COK, void, do_unsetmacro, (void),)
  758. {
  759.     DelMacro(av[1]);
  760. } /* do_unsetmacro */
  761.  
  762.  
  763. /*
  764. *!  >MACROSAVE filename
  765. *!    save the current macros into a file of a special format
  766. *!
  767. */
  768.  
  769. /*DEFHELP #cmd macro MACROSAVE filename - save all commandmacros into a file with a special format */
  770. DEFUSERCMD("MacroSave", 1, CF_VWM|CF_ICO, void, do_macrosave, (void),)
  771. {
  772.     std_writefile ((int (*) (FILE *, APTR))ALIAS_save, NULL);
  773. } /* do_macrosave */
  774.  
  775.  
  776. /*
  777. *!  >MACROLOAD filename
  778. *!    read a special macrofile
  779. *!
  780. */
  781.  
  782. /*DEFHELP #cmd macro MACROLOAD name -  load commandmacros from a file */
  783. DEFUSERCMD("MacroLoad", 1, CF_VWM|CF_ICO, void, do_macroload, (void),)
  784. {
  785.     int    lineno = 0;
  786.     std_readfile (ALIAS_load, &lineno);
  787. } /* do_macrosave */
  788.  
  789.  
  790. /******************************************************************************
  791. *****  END macros.c
  792. ******************************************************************************/
  793.  
  794. /* void PrintNode (struct Node *n) { printf ("PN: %08lx/`%s'\n", n, n->ln_Name); } */
  795.  
  796.